package main

import (
	"encoding/json"              // 处理JSON编解码（用于监控接口返回数据）
	"fmt"                        // 格式化字符串（用于生成节点类型、端口等）
	"gameServer/cluster/gate"    // 网关组件（客户端连接入口）
	"gameServer/cluster/node"    // 业务节点组件（处理具体游戏逻辑）
	"gameServer/health"          // 健康检查组件（监控服务存活状态）
	"gameServer/log"             // 日志输出（记录启动、错误等信息）
	"gameServer/registry"        // 服务注册中心接口（定义注册/查询规范）
	"gameServer/registry/memory" // 内存注册中心实现（具体存储服务信息）
	"net/http"                   // HTTP服务（实现监控接口）
	"os"                         // 系统信号处理
	"os/signal"
	"syscall"
	"time" // 时间处理（健康检查间隔、时间戳生成）
)

func main2() {
	/*
		共享实例：所有组件（网关、节点、健康检查）共用同一个注册中心，保证服务信息全局一致（若每个组件单独创建，会导致服务信息分散）。
		联动机制：注册中心负责 “存储服务”，定位器负责 “查找服务”，绑定后避免两者数据不一致（比如节点注销后，定位器能实时感知）。
	*/

	// 创建共享的注册中心实例
	memoryRegistry := memory.NewMemoryRegistry()
	// 创建内存定位器
	locator := memory.NewMemoryLocator()

	// 设置注册中心的定位器
	memoryRegistry.SetLocator(locator)

	// 创建健康检查器
	// 初始化健康检查器
	healthChecker := health.NewHealthChecker(memoryRegistry, 10*time.Second)
	// 创建网关组件
	gateComponent := gate.NewGate().SetTcpServer(":8781").SetRegistry(memoryRegistry).SetLocator(locator)

	/*

		集群部署：3 个节点实现负载均衡 —— 网关可将客户端请求分发到不同节点，避免单节点压力过大。
		请求类型 ID：用 ID 标识请求类型，比用字符串（如 “login”）更高效（二进制传输时占用字节少）。
		匿名函数处理：inline 定义处理逻辑，代码更紧凑；若后续需修改处理逻辑，直接修改匿名函数即可。

	*/

	// 创建多个节点组件
	nodes := make([]*node.Node, 3)
	for i := 0; i < 3; i++ {
		nodeType := fmt.Sprintf("game-%d", i)
		port := 9890 + i
		nodes[i] = node.NewNode(nodeType, "localhost", port).SetRegistry(memoryRegistry)
		// 给节点注册RPC处理函数：ID=1（标识请求类型），函数处理JSON请求
		nodes[i].RegisterRPCHandler(1, func(data []byte) ([]byte, error) {
			// 解析请求JSON（data是客户端发来的二进制数据）
			var request map[string]interface{}
			if err := json.Unmarshal(data, &request); err != nil {
				return nil, err // 解析失败返回错误
			}

			// 构造响应数据（包含原始请求、处理状态、时间戳、节点类型）
			response := map[string]interface{}{
				"original":  request,               // 原始请求数据
				"processed": true,                  // 标记请求已处理
				"timestamp": time.Now().UnixNano(), // 处理时间戳（纳秒级，确保唯一）
				"node":      nodeType,              // 处理请求的节点类型（方便定位节点）
			}

			// 响应数据JSON编码（返回二进制给调用方）
			return json.Marshal(response)
		})
	}
	// 启动所有组件
	log.Info("Starting health check demo...")
	// 启动健康检查器
	if err := healthChecker.Start(); err != nil {
		log.Fatalf("failed to start health checker: %v", err)
	}
	// 启动网关
	if err := gateComponent.Start(); err != nil {
		log.Fatalf("failed to start gate component: %v", err)
	}

	// 循环启动3个节点
	for i, node := range nodes {
		// 初始化节点（如初始化RPC服务、配置）
		if err := node.Init(); err != nil {
			log.Fatalf("failed to init node %d : %v", i, err)
		}

		// 启动节点（开始监听RPC请求，接收网关转发的请求）
		if err := node.Start(); err != nil {
			log.Fatalf("failed to start node %d : %v", i, err)
		}

		// 构造节点的服务信息（用于注册到健康检查器）
		serviceInfo := &registry.ServiceInfo{
			ID:      node.GetServiceID(), // 节点唯一ID（由节点内部生成，保证全局唯一）
			Name:    "node",              // 服务名称（用于按名称查询，如“node”类型的所有服务）
			Address: "localhost",         // 节点地址
			Port:    node.GetPort(),      // 节点RPC端口
			Metadata: map[string]string{ // 元数据（存储额外信息，如健康检查端口）
				"type":       node.GetNodeType(),                      // 节点类型（如game-0）
				"healthPort": fmt.Sprintf("%d", node.GetPort()+20000), // 健康检查端口（端口+20000，避免与RPC端口冲突）
			},
		}

		// 将节点注册到健康检查器（使用HTTP方式检查健康）
		if err := healthChecker.RegisterService(serviceInfo, health.DefaultHttpCheck); err != nil {
			log.Fatalf("failed to register health check for node %d : %v", i, err)
		}
	}
	// 启动http监控接口
	go startMonitoringServer(memoryRegistry, healthChecker)
	log.Info("All components started. Health monitoring available at http://localhost:9999/status")
	log.Info("Press Ctrl+C to stop.")

	// 等待终端信号
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
	<-sigChan
	// 停止组件
	log.Info("Shutting down components...")
	if err := gateComponent.Stop(); err != nil {
		log.Errorf("Failed to stop health checker: %v", err)
	}
	for i, node := range nodes {
		if err := node.Stop(); err != nil {
			log.Errorf("Failed to stop node %d : %v", i, err)
		}
	}
	if err := gateComponent.Stop(); err != nil {
		log.Errorf("Failed to stop gate component: %v", err)
	}
	log.Info("Health check demo completed")
}

// 启动监控服务器
func startMonitoringServer(Registry registry.Registry, healthChecker *health.HealthChecker) {
	http.HandleFunc("/status", func(w http.ResponseWriter, r *http.Request) {
		services, _ := Registry.ListServices()
		healthyServices, _ := Registry.ListHealthyServices()
		status := map[string]interface{}{
			"total_services":     len(services),
			"health_services":    len(healthyServices),
			"unhealthy_services": len(services) - len(healthyServices),
			"timestamp":          time.Now().Unix(),
		}
		w.Header().Set("Content-Type", "application/json")
		json.NewEncoder(w).Encode(status)
	})

	http.HandleFunc("/services", func(w http.ResponseWriter, r *http.Request) {
		services, _ := Registry.ListServices()
		w.Header().Set("Content-Type", "application/json")
		json.NewEncoder(w).Encode(services)
	})
	log.Info("Monitoring server starting on :9999")
	if err := http.ListenAndServe(":9999", nil); err != nil {
		log.Errorf("Monitoring server failed: %v", err)
	}
}
